<template>
  <div>
    <!-- 搜索区域 -->
    <van-search
      v-model="keyword"
      placeholder="请输入搜索关键词"
      shape="round"
      @input="debounceInputChange"
    />
    <div class="history-box" v-if="suggestList.length === 0">
      <van-tag
        plain
        type="primary"
        v-for="item in historyList"
        :key="item"
        class="tag-item"
        @click="goResult(item)"
      >
        {{ item }}
      </van-tag>
    </div>

    <!-- 搜索联想区域 -->
    <!--
      说明:因为后面还需要做点击跳转携带当前点击的联想关键词 为了保证关键词是原始的字符串
      不带span标签 所以我们采取的是只在模板区域对数据的显示做控制 而不动原来的字符数据列表
     -->
    <div class="sugg-list" v-else>
      <div
        class="sugg-item"
        v-for="item in suggestList"
        :key="item"
        @click="goResult(item)"
      >
        <span v-html="hightStr(item)"></span>
      </div>
    </div>
  </div>
</template>

<script>
/**
 * 渲染联想关键词列表
 * 1. 双向绑定
 * 2. input 回调中调用接口
 * 3. v-for
 *
 * 防抖
 * 1. 概念 在事件还在触发的过程中不执行回调 直到行为不再进行触发等到nms执行业务函数
 * 2. 三方插件 lodash 防抖 [推荐]
 * 3. 手写一个防抖
 *
 * 关键词高亮
 * 要求:只要列表中的每一项字符串中有和当前输入框中的关键词匹配的字符都变成红色 [不区分大小写 全局匹配]
 * 思路
 *   keyword = 'a'
 *  1. 'AbcDa' -> '<span style="color:red;">A</span>bcD<span style="color:red;">a</span>'
 *  2. 富文本识别 v-html
 *
 * * 记录历史
 * localStorage
 * 1. 点击关键词 存入ls
 * 2. 组件初始化的时候 优先从本地取一下 取不到初始化为[]
 */

import { getSuggestListAPI } from '@/api'

// 导入lodash
// import _ from 'lodash'

function debounce (fn, time) {
  let timer = null // 存放每次生成的延时器
  return function () {
    // 1.清理timer
    clearTimeout(timer)
    // 2.新建一个新的timer
    timer = setTimeout(() => {
      fn.call(this)
    }, time)
  }
}

export default {
  name: 'search-index',
  data () {
    return {
      keyword: '',
      suggestList: [],
      historyList: JSON.parse(localStorage.getItem('history')) || []
    }
  },
  methods: {
    // 要执行的业务逻辑函数
    async inputChange () {
      // 调用接口获取列表
      console.log('input')
      if (!this.keyword) {
        this.suggestList = []
      } else {
        const res = await getSuggestListAPI(this.keyword)
        this.suggestList = res.data.options
      }
    },
    // 防抖包裹函数
    // 注意:包裹防抖函数的写法时有可能遇到this绑定的问题
    // 第二个参数建议传递一个匿名函数 在匿名函数的内部 执行我们的业务函数

    // 思考: input事件触发的过程中执行的回调是谁？
    // debounceInputChange: _.debounce(function () {
    //   this.inputChange()
    // }, 500)

    // this问题说明
    // 1. fn.call(this) 让debounce函数第一个参数中的this指向call传入的this中
    // 2. call传入的this沿用父级作用域 return function函数中的this
    // 3. return function最终会被绑定到methods中的debounceInputChange属性上当成他的一个方法来调用
    // 4. methods中的任何一个方法 包括debounceInputChange方法 vue中执行的时候会被强制修正this指向当前的组件实例
    debounceInputChange: debounce(function () {
      // this不指向当前的组件实例对象
      this.inputChange()
    }, 500),
    // 字符串高亮处理函数
    hightStr (str) {
      // 处理 返回
      // 1. 正则不是固定的 正则表达式需要更具this.keyword动态生成 new Reg
      // 2. 替换的时候需要根据匹配到的关键词进行动态的替换 第二个参数回调函数函数写法
      // 动态生成一个正则表达式
      const reg = new RegExp(this.keyword, 'ig')
      return str.replace(reg, (key) => {
        // key表示当前的正则匹配到的那个字符串
        return `<span style="color:red;">${key}</span>`
      })
    },
    goResult (keyword) {
      // 把keyword存入本地 ['a','b']
      this.historyList.push(keyword)
      const uiqueList = [...new Set(this.historyList)]
      localStorage.setItem('history', JSON.stringify(uiqueList))
      this.$router.push({
        path: '/searchResult',
        query: {
          q: keyword
        }
      })
    }
  }
}
</script>

<style scoped lang="less">
/*搜索建议列表样式 */
.sugg-list {
  .sugg-item {
    padding: 0 15px;
    border-bottom: 1px solid #f8f8f8;
    font-size: 14px;
    line-height: 50px;
    // 实现省略号的三行代码
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: rgba(0, 0, 0, 0.65);
  }
}
.history-box {
  padding: 2px 14px;
  .tag-item {
    margin-right: 4px;
  }
}
</style>
